package com.bang.daybreak.common.config;

import com.github.benmanes.caffeine.cache.CacheLoader;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 配置caffeine缓存.
 * @EnableCaching:开启缓存
 * @author : wdj
 * @since : 2019/5/7 0007 上午 10:34
 * @version 1.0
 */
@Configuration
@EnableCaching
public class CaffeineConfig {
    public static final int DEFAULT_MAXSIZE = 10000;
    public static final int INITIAL_CAPACITY = 100;
    public static final int DEFAULT_TTL = 600;

    /**
     * 创建基于Caffeine的Cache Manager
     *
     * @return
     */
    @Bean
    public CacheManager caffeineCacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();

        Caffeine caffeine = Caffeine.newBuilder()
                // 初始的缓存空间大小
                .initialCapacity(INITIAL_CAPACITY)
                //maximumSize用来控制cache的最大缓存数量，maximumSize和maximumWeight不可以同时使用，
                .maximumSize(DEFAULT_MAXSIZE)
                //创建缓存或者最近一次更新缓存后经过固定的时间间隔，刷新缓存
                .refreshAfterWrite(5, TimeUnit.SECONDS)
                //后一次写入后经过固定时间过期;expireAfterWrite和expireAfterAccess同事存在时，以expireAfterWrite为准
                .expireAfterWrite(DEFAULT_TTL, TimeUnit.SECONDS);
        cacheManager.setCaffeine(caffeine);
        cacheManager.setCacheLoader(cacheLoader());
        cacheManager.setCacheNames(getCaffeineNames());
        return cacheManager;
    }

    /**
     * 必须要指定这个Bean，refreshAfterWrite=5s这个配置属性才生效
     *
     * @return
     */
    @Bean(name = "cacheLoader")
    public CacheLoader<Object, Object> cacheLoader() {

        CacheLoader<Object, Object> cacheLoader = new CacheLoader<Object, Object>() {

            @Override
            public Object load(Object key) throws Exception {
                return null;
            }

            // 重写这个方法将oldValue值返回回去，进而刷新缓存
            @Override
            public Object reload(Object key, Object oldValue) throws Exception {
                return oldValue;
            }
        };

        return cacheLoader;
    }

    /**
     * 指定缓存名称
     *
     * @return
     */
    private static List<String> getCaffeineNames() {
        List<String> names = new ArrayList<>(1);
        names.add("searchConfig");
        return names;
    }

}
